/* copyright 2000-2008 Dead_Body */
/* version 1.05 - its complete, then improved and updated
	todo:
		begin improvements
		do something with opcodes, looks ugly
		remove long star bar comments
		sprintf?
		function names
		the tables
		read/write handling
	thanks to:
		[_TRAC_]
		mdw2
		GreyBrain
		TNSe
		nyef
		Azimer
		Delta
		kevtris
   compiling: there are some defines you can do:
     NES - dont include adc/sbc decimal mode stuff
     JMPBUG - make the indirect jmp have the bug, just like the real nes 6502
     SKIPBADOPS - skip over bad opcodes instead of returning an error
     CPUDEBUG - debug the cpu core (or debug a rom...)                                          */
/************************************************************************************************/
//#define NES
#define JMPBUG
//#define SKIPBADOPS
//#define CPUDEBUG
#define MSGFUNC
/************************************************************************************************/
#ifdef _WINDOWS //prolly msvc (i hope so :P)
#pragma warning(disable:4244)	//nasty warning, conversion from bleh to blah, possible loss of data
#endif
#undef SPRINTF
#if defined(WIN32)
	#include <windows.h>
	#define SPRINTF wsprintf
#else
	#include <stdio.h>
	#define SPRINTF sprintf
#endif
#ifdef CPUDEBUG
	#ifdef MSGFUNC
//		extern void msg(char *,...);
		#define msg message
	#else
		#include <stdio.h>
		#define msg	printf
	#endif
#endif
#define __DEAD6502COMPILED__
#include "dead6502.h"
/************************************************************************************************/
#define checknz(b)\
	d6502_f &= 0x7d;\
	d6502_f |= nztable[b];
#define push(b)\
	{\
	a = (u32)(d6502_s-- | 0x100);\
	d6502_write6502(a,(u8)(b));\
	}
#define pop(b)\
	{\
	a = (u32)(++d6502_s | 0x100);\
	(b) = d6502_read6502(a);\
	}
#define INLINE						__inline
#define EXTRA_CYCLE				1
#define am_xxx						0
#define op_xxx						0
#define op_xxx_xxx				0
#define NMI_MASK					0xfe
#define IRQ_MASK					0xfd
#define NZ							0x82
#define NZ_MASK					0x7d
#define FLAG_NEGATIVE			0x80
#define FLAG_OVERFLOW			0x40
#define FLAG_XXX					0x20
#define FLAG_BRK					0x10
#define FLAG_DECIMAL				0x08
#define FLAG_IRQDISABLE			0x04
#define FLAG_ZERO					0x02
#define FLAG_CARRY				0x01
#define FLAG_NEGATIVE_MASK		0x7f
#define FLAG_OVERFLOW_MASK		0xbf
#define FLAG_XXX_MASK			0xdf
#define FLAG_BRK_MASK			0xef
#define FLAG_DECIMAL_MASK		0xf7
#define FLAG_IRQDISABLE_MASK	0xfb
#define FLAG_ZERO_MASK			0xfd
#define FLAG_CARRY_MASK			0xfe
#define OFFSET_A					0
#define OFFSET_X					(OFFSET_A + 4)
#define OFFSET_Y					(OFFSET_X + 4)
#define OFFSET_S					(OFFSET_Y + 4)
#define OFFSET_F					(OFFSET_S + 4)
#define OFFSET_PC					(OFFSET_F + 4)
#define OFFSET_TOTALCYCLES		(OFFSET_PC + 4)
#define OFFSET_NEEDIRQ			(OFFSET_TOTALCYCLES + 4)
#define OFFSET_OP6502			(OFFSET_NEEDIRQ + 4)
#define OFFSET_READ6502			(OFFSET_OP6502 + 4)
#define OFFSET_WRITE6502		(OFFSET_READ6502 + 4)
#define OFFSET_OPPAGES			(OFFSET_WRITE6502 + 4)
#define OFFSET_READPAGES		(OFFSET_OPPAGES + (PAGE_NUM * 4))
#define OFFSET_WRITEPAGES		(OFFSET_READPAGES + (PAGE_NUM * 4))
/************************************************************************************************/
typedef void(*voidcall)();
/************************************************************************************************/
static u8 stop;
static u32 tcycles;
static u32 a;
static u8 oldop,saveop;
static u16 oldpc,savepc;
static dead6502data *data;
#define d6502_a data->a
#define d6502_x data->x
#define d6502_y data->y
#define d6502_s data->s
#define d6502_f data->f
#define d6502_pc data->pc
#define d6502_eaddr data->eaddr
#define d6502_totalcycles data->totalcycles
#define d6502_needirq data->needirq
#define d6502_userdata data->userdata
#define d6502_opcode data->opcode
static u32 framecycles;
static u32 scanlinecycles;
static u8 nmicycles;
static u8 irqcycles;
static u32 cyclesexec;
static u16 addr,addrtmp;
static u8 value;
enum addrmodes {er=0,no,ab,ax,ay,ac,im,ix,iy,in,re,zp,zx,zy};
static u8 cycletable[256];
static u8 nztable[256];
static u8 basecycletable[256] =
	{
	7,6,0,0,0,3,5,0,3,2,2,0,0,4,6,0, /* 00-0f */
	2,5,0,0,0,4,6,0,2,4,0,0,0,4,6,0, /* 10-1f */
	6,6,0,0,3,3,5,0,4,2,2,0,4,4,6,0, /* 20-2f */
	2,5,0,0,0,4,6,0,2,4,0,0,0,4,6,0, /* 30-3f */
	6,6,0,0,0,3,5,0,3,2,2,0,3,4,6,0, /* 40-4f */
	2,5,0,0,0,4,6,0,2,4,0,0,0,4,6,0, /* 50-5f */
	6,6,0,0,0,3,5,0,4,2,2,0,5,4,6,0, /* 60-6f */
	2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, /* 70-7f */
	0,6,0,0,3,3,3,0,2,0,2,0,4,4,4,0, /* 80-8f */
	2,6,0,0,4,4,4,0,2,5,2,0,0,5,0,0, /* 90-9f */
	2,6,2,0,3,3,3,0,2,2,2,0,4,4,4,0, /* a0-af */
	2,5,0,0,4,4,4,0,2,4,2,0,4,4,4,0, /* b0-bf */
	2,6,0,0,3,3,5,0,2,2,2,0,4,4,6,0, /* c0-cf */
	2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, /* d0-df */
	2,6,0,0,3,3,5,0,2,2,2,0,4,4,6,0, /* e0-ef */
	2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0  /* f0-ff */
	};
static char opcodes[256][4] = 
	{
 	"brk","ora","???","???","???","ora","asl","???", //00-07
	"php","ora","asl","???","???","ora","asl","???", //08-0f
	"bpl","ora","???","???","???","ora","asl","???", //10-17
	"clc","ora","???","???","???","ora","asl","???", //18-1f
	"jsr","and","???","???","bit","and","rol","???", //20-27
	"plp","and","rol","???","bit","and","rol","???", //28-2f
	"bmi","and","???","???","???","and","rol","???", //20-27
	"sec","and","???","???","???","and","rol","???", //38-3f
	"rti","eor","???","???","???","eor","lsr","???", //30-37
	"pha","eor","lsr","???","jmp","eor","lsr","???", //48-4f
	"bvc","eor","???","???","???","eor","lsr","???", //40-47
	"cli","eor","???","???","???","eor","lsr","???", //58-5f
	"rts","adc","???","???","???","adc","ror","???", //50-57
	"pla","adc","ror","???","jmp","adc","ror","???", //68-6f
	"bvs","adc","???","???","???","adc","ror","???", //60-67
	"sei","adc","???","???","???","adc","ror","???", //78-7f
	"???","sta","???","???","sty","sta","stx","???", //80-87
	"dey","???","txa","???","sty","sta","stx","???", //88-8f
	"bcc","sta","???","???","sty","sta","stx","???", //90-97
	"tya","sta","txs","???","???","sta","???","???", //98-9f
	"ldy","lda","ldx","???","ldy","lda","ldx","???", //a0-a7
	"tay","lda","tax","???","ldy","lda","ldx","???", //a8-af
	"bcs","lda","???","???","ldy","lda","ldx","???", //b0-b7
	"clv","lda","tsx","???","ldy","lda","ldx","???", //b8-bf
	"cpy","cmp","???","???","cpy","cmp","dec","???", //c0-c7
	"iny","cmp","dex","???","cpy","cmp","dec","???", //c8-cf
	"bne","cmp","???","???","???","cmp","dec","???", //d0-d7
	"cld","cmp","???","???","???","cmp","dec","???", //d8-df
	"cpx","sbc","???","???","cpx","sbc","inc","???", //e0-e7
	"inx","sbc","nop","???","cpx","sbc","inc","???", //e8-ef
	"beq","sbc","???","???","???","sbc","inc","???", //f0-f7
	"sed","sbc","???","???","???","sbc","inc","???"  //f8-ff
	};
static u8 addrtable[256] =
	{
   no,ix,er,er,er,zp,zp,er, //00-07
	no,im,ac,er,er,ab,ab,er, //08-0f
   re,iy,er,er,er,zx,zx,er, //10-17
	no,ay,er,er,er,ax,ax,er, //18-1f
   ab,ix,er,er,zp,zp,zp,er, //20-27
	no,im,ac,er,ab,ab,ab,er, //28-2f
   re,iy,er,er,er,zx,zx,er, //30-37
	no,ay,er,er,er,ax,ax,er, //38-3f
   no,ix,er,er,er,zp,zp,er, //40-47
	no,im,ac,er,ab,ab,ab,er, //48-4f
   re,iy,er,er,er,zx,zx,er, //50-57
	no,ay,er,er,er,ax,ax,er, //58-5f
   no,ix,er,er,er,zp,zp,er, //60-67
	no,im,ac,er,in,ab,ab,er, //68-6f
   re,iy,er,er,er,zx,zx,er, //70-77
	no,ay,er,er,er,ax,ax,er, //78-7f
 	er,ix,er,er,zp,zp,zp,er, //80-87
	no,er,no,er,ab,ab,ab,er, //88-8f
   re,iy,er,er,zx,zx,zy,er, //90-97
	no,ay,no,er,er,ax,er,er, //98-9f
   im,ix,im,er,zp,zp,zp,er, //a0-a7
	no,im,no,er,ab,ab,ab,er, //a8-af
   re,iy,er,er,zx,zx,zy,er, //b0-b7
	no,ay,no,er,ax,ax,ay,er, //b8-bf
   im,ix,er,er,zp,zp,zp,er, //c0-c7
	no,im,no,er,ab,ab,ab,er, //c8-cf
   re,iy,er,er,er,zx,zx,er, //d0-d7
	no,ay,er,er,er,ax,ax,er, //d8-df
   im,ix,er,er,zp,zp,zp,er, //e0-e7
	no,im,no,er,ab,ab,ab,er, //e8-ef
   re,iy,er,er,er,zx,zx,er, //f0-f7
	no,ay,er,er,er,ax,ax,er  //f8-ff
   };
static u8 oplength[256];/* = 
	{
	1,2,0,0,0,2,2,0, //00-07
	1,2,1,0,0,3,3,0, //08-0f
	2,2,0,0,0,2,2,0, //10-17
	1,3,0,0,0,3,3,0, //18-1f
	3,2,0,0,2,2,2,0, //20-27
	1,2,1,0,3,3,3,0, //28-2f
	2,2,0,0,0,2,2,0, //30-37
	1,3,0,0,0,3,3,0, //38-3f
	1,2,0,0,0,2,2,0, //40-47
	1,2,1,0,3,3,3,0, //48-4f
	2,2,0,0,0,2,2,0, //50-57
	1,3,0,0,0,3,3,0, //58-5f
	1,2,0,0,1,2,2,0, //60-67
	1,2,1,0,3,3,3,0, //68-6f
	2,2,0,0,1,2,2,0, //70-77
	1,3,0,0,1,3,3,0, //78-7f
	0,2,0,0,2,2,2,0, //80-87
	1,0,1,0,3,3,3,0, //88-8f
	2,2,0,0,2,2,2,0, //90-97
	1,3,1,0,0,3,0,0, //98-9f
	2,2,2,0,2,2,2,0, //a0-a7
	1,2,1,0,3,3,3,0, //a8-af
	2,2,0,0,2,2,2,0, //b0-b7
	1,3,1,0,3,3,3,0, //b8-bf
	2,2,0,0,2,2,2,0, //c0-c7
	1,2,1,0,3,3,3,0, //c8-cf
	2,2,0,0,0,2,2,0, //d0-d7
	1,3,0,0,0,3,3,0, //d8-df
	2,2,0,0,2,2,2,0, //e0-e7
	1,2,1,0,3,3,3,0, //e8-ef
	2,2,0,0,0,2,2,0, //f0-f7
	1,3,0,0,0,3,3,0  //f8-ff
	};*/
/************************************************************************************************/
#define branch(cond)\
{\
if(cond)\
	{\
	value = d6502_read6502(d6502_pc);\
	d6502_pc++;\
	addrtmp = d6502_pc + (s8)value;\
	if((addrtmp ^ d6502_pc) & 0xff00)\
		cyclesexec++;\
	d6502_pc = addrtmp;\
	cyclesexec++;\
	}\
else\
	d6502_pc++;\
}
/************************************************************************************************/
INLINE u8 d6502_op6502(u32 address)
{
u8 *page = data->oppages[address >> DEAD6502_PAGE_SHIFT];

data->lastread = address;
if(page)
	return(page[address & DEAD6502_PAGE_MASK]);
return(data->op6502(d6502_userdata,address));
}
/************************************************************************************************/
INLINE u8 d6502_read6502(u32 address)
{
u8 *page = data->readpages[address >> DEAD6502_PAGE_SHIFT];

data->lastread = address;
if(page)
	return(page[address & DEAD6502_PAGE_MASK]);
return(data->read6502(d6502_userdata,address));
}
/************************************************************************************************/
INLINE void d6502_write6502(u32 address,u8 value)
{
u8 *page = data->writepages[address >> DEAD6502_PAGE_SHIFT];

data->lastwrite = address;
if(page)
	page[address & DEAD6502_PAGE_MASK] = value;
else
	data->write6502(d6502_userdata,address,value);
}
/************************************************************************************************/
INLINE void op_brk()
{
d6502_pc++;
d6502_f |= FLAG_BRK;
push(d6502_pc >> 8);
push(d6502_pc);
push(d6502_f);
d6502_f |= FLAG_IRQDISABLE;
d6502_pc = d6502_read6502(0xfffe);
d6502_pc |= d6502_read6502(0xffff) << 8;
}
/************************************************************************************************/
INLINE void op_ora()
{
d6502_a |= d6502_read6502(addr);
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void op_asl()
{
value = d6502_read6502(addr);
d6502_f &= FLAG_CARRY_MASK;
if(value & 0x80)
	d6502_f |= FLAG_CARRY;
value = value << 1;
d6502_write6502(addr,value);
checknz(value);
}
/************************************************************************************************/
INLINE void op_php()
{
push(d6502_f | FLAG_BRK);
}
/************************************************************************************************/
INLINE void op_clc()
{
d6502_f &= FLAG_CARRY_MASK;
}
/************************************************************************************************/
INLINE void op_jsr()
{
d6502_pc--;
push(d6502_pc >> 8);
push(d6502_pc);
d6502_pc = addr;
}
/************************************************************************************************/
INLINE void op_and()
{
d6502_a &= d6502_read6502(addr);
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void op_bit()
{
value = d6502_read6502(addr);
d6502_f &= 0x3d; /* clear negative, overflow and zero */
d6502_f |= value & 0xc0; /* set negative and overflow */
if((d6502_a & value) == 0)
	d6502_f |= FLAG_ZERO;
}
/************************************************************************************************/
INLINE void op_rol()
{
value = d6502_read6502(addr);
if(value & 0x80)
	{
	value = value << 1;
	value |= d6502_f & 1; /* carry flag is bit0, hehe */
	d6502_f |= FLAG_CARRY;
	}
else
	{
	value = value << 1;
	value |= d6502_f & 1;
	d6502_f &= FLAG_CARRY_MASK;
	}
d6502_write6502(addr,value);
checknz(value);
}
/************************************************************************************************/
INLINE void op_plp()
{
pop(d6502_f);
d6502_f |= FLAG_XXX;
}
/************************************************************************************************/
INLINE void op_sec()
{
d6502_f |= FLAG_CARRY;
}
/************************************************************************************************/
INLINE void op_rti()
{
pop(d6502_f);
pop(d6502_pc);
pop(value);
d6502_f |= FLAG_XXX;
d6502_pc |= value << 8;
}
/************************************************************************************************/
INLINE void op_eor()
{
d6502_a ^= d6502_read6502(addr);
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void op_lsr()
{
value = d6502_read6502(addr);
d6502_f &= FLAG_CARRY_MASK;
d6502_f |= value & 1;
value = value >> 1;
d6502_write6502(addr,value);
checknz(value);
}
/************************************************************************************************/
INLINE void op_pha()
{
push(d6502_a);
}
/************************************************************************************************/
INLINE void op_jmp()
{
d6502_pc = addr;
}
/************************************************************************************************/
INLINE void op_cli()
{
d6502_f &= FLAG_IRQDISABLE_MASK;
}
/************************************************************************************************/
INLINE void op_rts()
{
pop(d6502_pc);
pop(value);
d6502_pc |= value << 8;
d6502_pc++;
}
/************************************************************************************************/
INLINE void op_adc()
{
u16 newa;

value = d6502_read6502(addr);
newa = d6502_a + value + (d6502_f & FLAG_CARRY); /* how convenient, carry flag is bit0  :) */
d6502_f &= 0xbe; /* clear carry and overflow flags */
if(newa & 0xff00)
	d6502_f |= FLAG_CARRY;
d6502_f |= (((d6502_a ^ newa) & (value ^ newa)) & 0x80) >> 1;
d6502_a = newa & 0xff;
#ifndef NES
if(d6502_f & FLAG_DECIMAL)
	{
	d6502_f &= FLAG_CARRY_MASK;
	if((d6502_a & 0x0f) > 0x09)
		d6502_a += 0x06;
	if((d6502_a & 0xf0) > 0x90)
		{
		d6502_a += 0x60;
		d6502_f |= FLAG_CARRY;
		}
	}
#endif
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void op_ror()
{
value = d6502_read6502(addr);
if(value & 1)
	{
	value = value >> 1;
	if(d6502_f & FLAG_CARRY)
		value |= 0x80;
	d6502_f |= FLAG_CARRY;
	}
else
	{
	value = value >> 1;
	if(d6502_f & FLAG_CARRY)
		value |= 0x80;
	d6502_f &= FLAG_CARRY_MASK;
	}
d6502_write6502(addr,value);
checknz(value);
}
/************************************************************************************************/
INLINE void op_pla()
{
pop(d6502_a);
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void op_sei()
{
d6502_f |= FLAG_IRQDISABLE;
}
/************************************************************************************************/
INLINE void op_sta()
{
d6502_write6502(addr,d6502_a);
}
/************************************************************************************************/
INLINE void op_sty()
{
d6502_write6502(addr,d6502_y);
}
/************************************************************************************************/
INLINE void op_stx()
{
d6502_write6502(addr,d6502_x);
}
/************************************************************************************************/
INLINE void op_dey()
{
d6502_y--;
checknz(d6502_y);
}
/************************************************************************************************/
INLINE void op_txa()
{
d6502_a = d6502_x;
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void op_tya()
{
d6502_a = d6502_y;
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void op_txs()
{
d6502_s = d6502_x;
checknz(d6502_s);
}
/************************************************************************************************/
INLINE void op_ldy()
{
d6502_y = d6502_read6502(addr);
checknz(d6502_y);
}
/************************************************************************************************/
INLINE void op_lda()
{
d6502_a = d6502_read6502(addr);
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void op_ldx()
{
d6502_x = d6502_read6502(addr);
checknz(d6502_x);
}
/************************************************************************************************/
INLINE void op_tay()
{
d6502_y = d6502_a;
checknz(d6502_y);
}
/************************************************************************************************/
INLINE void op_tax()
{
d6502_x = d6502_a;
checknz(d6502_x);
}
/************************************************************************************************/
INLINE void op_clv()
{
d6502_f &= FLAG_OVERFLOW_MASK;
}
/************************************************************************************************/
INLINE void op_tsx()
{
d6502_x = d6502_s;
checknz(d6502_x);
}
/************************************************************************************************/
INLINE void op_cpy()
{
u16 newvalue;

newvalue = (d6502_y + 0x100) - d6502_read6502(addr);
d6502_f &= FLAG_CARRY_MASK;
if(newvalue & 0xff00)
	d6502_f |= FLAG_CARRY;
newvalue &= 0xff;
checknz(newvalue);
}
/************************************************************************************************/
INLINE void op_cmp()
{
u16 newvalue;

newvalue = (d6502_a + 0x100) - d6502_read6502(addr);
d6502_f &= FLAG_CARRY_MASK;
if(newvalue & 0xff00)
	d6502_f |= FLAG_CARRY;
newvalue &= 0xff;
checknz(newvalue);
}
/************************************************************************************************/
INLINE void op_dec()
{
value = d6502_read6502(addr);
value--;
d6502_write6502(addr,value);
checknz(value);
}
/************************************************************************************************/
INLINE void op_iny()
{
d6502_y++;
checknz(d6502_y);
}
/************************************************************************************************/
INLINE void op_dex()
{
d6502_x--;
checknz(d6502_x);
}
/************************************************************************************************/
INLINE void op_cld()
{
d6502_f &= FLAG_DECIMAL_MASK;
}
/************************************************************************************************/
INLINE void op_cpx()
{
u16 newvalue;

newvalue = (d6502_x + 0x100) - d6502_read6502(addr);
d6502_f &= FLAG_CARRY_MASK;
if(newvalue & 0xff00)
	d6502_f |= FLAG_CARRY;
newvalue &= 0xff;
checknz(newvalue);
}
/************************************************************************************************/
INLINE void op_sbc()
{
u16 newa;

value = d6502_read6502(addr);
newa = d6502_a - value - (1 - (d6502_f & FLAG_CARRY));
d6502_f &= 0xbe; /* clear carry and overflow flags */
if(!(newa & 0xff00))
	d6502_f |= FLAG_CARRY;
d6502_f |= (((d6502_a ^ value) & (d6502_a ^ newa)) & 0x80) >> 1;
d6502_a = newa & 0xff;
#ifndef NES
if(d6502_f & FLAG_DECIMAL)
	{
	d6502_a -= 0x66;
	d6502_f &= FLAG_CARRY_MASK;
	if((d6502_a & 0x0f) > 0x09)
		d6502_a += 0x06;
	if((d6502_a & 0xf0) > 0x90)
		{
		d6502_a += 0x60;
		d6502_f |= FLAG_CARRY;
		}
	}
#endif
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void op_inc()
{
value = d6502_read6502(addr);
value++;
d6502_write6502(addr,value);
checknz(value);
}
/************************************************************************************************/
INLINE void op_inx()
{
d6502_x++;
checknz(d6502_x);
}
/************************************************************************************************/
INLINE void op_nop()
{
/* do nothing */
}
/************************************************************************************************/
INLINE void op_sed()
{
d6502_f |= FLAG_DECIMAL;
}
/************************************************************************************************/
INLINE void ac_asl()
{
d6502_f &= FLAG_CARRY_MASK;
if(d6502_a & 0x80)
	d6502_f |= FLAG_CARRY;
d6502_a = d6502_a << 1;
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void ac_rol()
{
if(d6502_a & 0x80)
	{
	d6502_a = d6502_a << 1;
	d6502_a |= d6502_f & 1; /* carry flag is bit0, hehe */
	d6502_f |= FLAG_CARRY;
	}
else
	{
	d6502_a = d6502_a << 1;
	d6502_a |= d6502_f & 1;
	d6502_f &= FLAG_CARRY_MASK;
	}
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void ac_lsr()
{
d6502_f &= FLAG_CARRY_MASK;
d6502_f |= d6502_a & 1;
d6502_a = d6502_a >> 1;
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void ac_ror()
{
if(d6502_a & 1)
	{
	d6502_a = d6502_a >> 1;
	if(d6502_f & FLAG_CARRY)
		d6502_a |= 0x80;
	d6502_f |= FLAG_CARRY;
	}
else
	{
	d6502_a = d6502_a >> 1;
	if(d6502_f & FLAG_CARRY)
		d6502_a |= 0x80;
	d6502_f &= FLAG_CARRY_MASK;
	}
checknz(d6502_a);
}
/************************************************************************************************/
INLINE void am_abs()
{
addr = d6502_read6502(d6502_pc++);
addr |= d6502_read6502(d6502_pc++) << 8;
}
/************************************************************************************************/
INLINE void am_abx()
{
addr = d6502_read6502(d6502_pc++);
addr += d6502_x;
if(addr & 0xff00)
	cyclesexec += EXTRA_CYCLE;
addr += d6502_read6502(d6502_pc++) << 8;
}
/************************************************************************************************/
INLINE void am_aby()
{
addr = d6502_read6502(d6502_pc++);
addr += d6502_y;
if(addr & 0xff00)
	cyclesexec += EXTRA_CYCLE;
addr += d6502_read6502(d6502_pc++) << 8;
}
/************************************************************************************************/
INLINE void am_imm()
{
addr = d6502_pc++;
}
/************************************************************************************************/
INLINE void am_ind()
{
u16 p00p;

p00p = d6502_read6502(d6502_pc++);
p00p |= d6502_read6502(d6502_pc++) << 8;
#ifdef JMPBUG
	addr = d6502_read6502(p00p);
	if((p00p & 0xff) == 0xff)
		p00p &= 0xff00;
	else
		p00p++;
	addr |= d6502_read6502(p00p) << 8;
#else
	addr = d6502_read6502(p00p++);
	addr |= d6502_read6502(p00p) << 8;
#endif
}
/***********************************************************************************************/
INLINE void am_inx()
{
u8 zpaddr;

zpaddr = d6502_read6502(d6502_pc++);
zpaddr += d6502_x;
addr = d6502_read6502(zpaddr++);
addr |= d6502_read6502(zpaddr) << 8;
}
/************************************************************************************************/
INLINE void am_iny()
{
u8 zpaddr;

zpaddr = d6502_read6502(d6502_pc++);
addr = d6502_read6502(zpaddr++);
addr += d6502_y;
if(addr & 0xff00)
	cyclesexec++;
addr += d6502_read6502(zpaddr) << 8;
}
/************************************************************************************************/
INLINE void am_zpg()
{
addr = d6502_read6502(d6502_pc++);
}
/************************************************************************************************/
INLINE void am_zpx()
{
addr = d6502_read6502(d6502_pc++);
addr += d6502_x;
addr &= 0xff;
}
/************************************************************************************************/
INLINE void am_zpy()
{
addr = d6502_read6502(d6502_pc++);
addr += d6502_y;
addr &= 0xff;
}
/************************************************************************************************/
static void op_brk_imp()
{
op_brk();
}
/************************************************************************************************/
static void op_ora_inx()
{
am_inx();
op_ora();
}
/************************************************************************************************/
static void op_ora_zpg()
{
am_zpg();
op_ora();
}
/************************************************************************************************/
static void op_asl_zpg()
{
am_zpg();
op_asl();
}
/************************************************************************************************/
static void op_php_imp()
{
op_php();
}
/************************************************************************************************/
static void op_ora_imm()
{
am_imm();
op_ora();
}
/************************************************************************************************/
static void op_asl_acc()
{
ac_asl();
}
/************************************************************************************************/
static void op_ora_abs()
{
am_abs();
op_ora();
}
/************************************************************************************************/
static void op_asl_abs()
{
am_abs();
op_asl();
}
/************************************************************************************************/
static void op_bpl_rel()
{
branch((d6502_f & FLAG_NEGATIVE) == 0);
}
/************************************************************************************************/
static void op_ora_iny()
{
am_iny();
op_ora();
}
/************************************************************************************************/
static void op_ora_zpx()
{
am_zpx();
op_ora();
}
/************************************************************************************************/
static void op_asl_zpx()
{
am_zpx();
op_asl();
}
/************************************************************************************************/
static void op_clc_imp()
{
op_clc();
}
/************************************************************************************************/
static void op_ora_aby()
{
am_aby();
op_ora();
}
/************************************************************************************************/
static void op_ora_abx()
{
am_abx();
op_ora();
}
/************************************************************************************************/
static void op_asl_abx()
{
am_abx();
op_asl();
}
/************************************************************************************************/
static void op_jsr_abs()
{
am_abs();
op_jsr();
}
/************************************************************************************************/
static void op_and_inx()
{
am_inx();
op_and();
}
/************************************************************************************************/
static void op_bit_zpg()
{
am_zpg();
op_bit();
}
/************************************************************************************************/
static void op_and_zpg()
{
am_zpg();
op_and();
}
/************************************************************************************************/
static void op_rol_zpg()
{
am_zpg();
op_rol();
}
/************************************************************************************************/
static void op_plp_imp()
{
op_plp();
}
/************************************************************************************************/
static void op_and_imm()
{
am_imm();
op_and();
}
/************************************************************************************************/
static void op_rol_acc()
{
ac_rol();
}
/************************************************************************************************/
static void op_bit_abs()
{
am_abs();
op_bit();
}
/************************************************************************************************/
static void op_and_abs()
{
am_abs();
op_and();
}
/************************************************************************************************/
static void op_rol_abs()
{
am_abs();
op_rol();
}
/************************************************************************************************/
static void op_bmi_rel()
{
branch(d6502_f & FLAG_NEGATIVE);
}
/************************************************************************************************/
static void op_and_iny()
{
am_iny();
op_and();
}
/************************************************************************************************/
static void op_and_zpx()
{
am_zpx();
op_and();
}
/************************************************************************************************/
static void op_rol_zpx()
{
am_zpx();
op_rol();
}
/************************************************************************************************/
static void op_sec_imp()
{
op_sec();
}
/************************************************************************************************/
static void op_and_aby()
{
am_aby();
op_and();
}
/************************************************************************************************/
static void op_and_abx()
{
am_abx();
op_and();
}
/************************************************************************************************/
static void op_rol_abx()
{
am_abx();
op_rol();
}
/************************************************************************************************/
static void op_rti_imp()
{
op_rti();
}
/************************************************************************************************/
static void op_eor_inx()
{
am_inx();
op_eor();
}
/************************************************************************************************/
static void op_eor_zpg()
{
am_zpg();
op_eor();
}
/************************************************************************************************/
static void op_lsr_zpg()
{
am_zpg();
op_lsr();
}
/************************************************************************************************/
static void op_pha_imp()
{
op_pha();
}
/************************************************************************************************/
static void op_eor_imm()
{
am_imm();
op_eor();
}
/************************************************************************************************/
static void op_lsr_acc()
{
ac_lsr();
}
/************************************************************************************************/
static void op_jmp_abs()
{
am_abs();
op_jmp();
}
/************************************************************************************************/
static void op_eor_abs()
{
am_abs();
op_eor();
}
/************************************************************************************************/
static void op_lsr_abs()
{
am_abs();
op_lsr();
}
/************************************************************************************************/
static void op_bvc_rel()
{
branch((d6502_f & FLAG_OVERFLOW) == 0);
}
/************************************************************************************************/
static void op_eor_iny()
{
am_iny();
op_eor();
}
/************************************************************************************************/
static void op_eor_zpx()
{
am_zpx();
op_eor();
}
/************************************************************************************************/
static void op_lsr_zpx()
{
am_zpx();
op_lsr();
}
/************************************************************************************************/
static void op_cli_imp()
{
op_cli();
}
/************************************************************************************************/
static void op_eor_aby()
{
am_aby();
op_eor();
}
/************************************************************************************************/
static void op_eor_abx()
{
am_abx();
op_eor();
}
/************************************************************************************************/
static void op_lsr_abx()
{
am_abx();
op_lsr();
}
/************************************************************************************************/
static void op_rts_imp()
{
op_rts();
}
/************************************************************************************************/
static void op_adc_inx()
{
am_inx();
op_adc();
}
/************************************************************************************************/
static void op_adc_zpg()
{
am_zpg();
op_adc();
}
/************************************************************************************************/
static void op_ror_zpg()
{
am_zpg();
op_ror();
}
/************************************************************************************************/
static void op_pla_imp()
{
op_pla();
}
/************************************************************************************************/
static void op_adc_imm()
{
am_imm();
op_adc();
}
/************************************************************************************************/
static void op_ror_acc()
{
ac_ror();
}
/************************************************************************************************/
static void op_jmp_ind()
{
am_ind();
op_jmp();
}
/************************************************************************************************/
static void op_adc_abs()
{
am_abs();
op_adc();
}
/************************************************************************************************/
static void op_ror_abs()
{
am_abs();
op_ror();
}
/************************************************************************************************/
static void op_bvs_rel()
{
branch(d6502_f & FLAG_OVERFLOW);
}
/************************************************************************************************/
static void op_adc_iny()
{
am_iny();
op_adc();
}
/************************************************************************************************/
static void op_adc_zpx()
{
am_zpx();
op_adc();
}
/************************************************************************************************/
static void op_ror_zpx()
{
am_zpx();
op_ror();
}
/************************************************************************************************/
static void op_sei_imp()
{
op_sei();
}
/************************************************************************************************/
static void op_adc_aby()
{
am_aby();
op_adc();
}
/************************************************************************************************/
static void op_adc_abx()
{
am_abx();
op_adc();
}
/************************************************************************************************/
static void op_ror_abx()
{
am_abx();
op_ror();
}
/************************************************************************************************/
static void op_sta_inx()
{
am_inx();
op_sta();
}
/************************************************************************************************/
static void op_sty_zpg()
{
am_zpg();
op_sty();
}
/************************************************************************************************/
static void op_sta_zpg()
{
am_zpg();
op_sta();
}
/************************************************************************************************/
static void op_stx_zpg()
{
am_zpg();
op_stx();
}
/************************************************************************************************/
static void op_dey_imp()
{
op_dey();
}
/************************************************************************************************/
static void op_txa_imp()
{
op_txa();
}
/************************************************************************************************/
static void op_sty_abs()
{
am_abs();
op_sty();
}
/************************************************************************************************/
static void op_sta_abs()
{
am_abs();
op_sta();
}
/************************************************************************************************/
static void op_stx_abs()
{
am_abs();
op_stx();
}
/************************************************************************************************/
static void op_bcc_rel()
{
branch((d6502_f & FLAG_CARRY) == 0);
}
/************************************************************************************************/
static void op_sta_iny()
{
am_iny();
op_sta();
}
/************************************************************************************************/
static void op_sty_zpx()
{
am_zpx();
op_sty();
}
/************************************************************************************************/
static void op_sta_zpx()
{
am_zpx();
op_sta();
}
/************************************************************************************************/
static void op_stx_zpy()
{
am_zpy();
op_stx();
}
/************************************************************************************************/
static void op_tya_imp()
{
op_tya();
}
/************************************************************************************************/
static void op_sta_aby()
{
am_aby();
op_sta();
}
/************************************************************************************************/
static void op_txs_imp()
{
op_txs();
}
/************************************************************************************************/
static void op_sta_abx()
{
am_abx();
op_sta();
}
/************************************************************************************************/
static void op_ldy_imm()
{
am_imm();
op_ldy();
}
/************************************************************************************************/
static void op_lda_inx()
{
am_inx();
op_lda();
}
/************************************************************************************************/
static void op_ldx_imm()
{
am_imm();
op_ldx();
}
/************************************************************************************************/
static void op_ldy_zpg()
{
am_zpg();
op_ldy();
}
/************************************************************************************************/
static void op_lda_zpg()
{
am_zpg();
op_lda();
}
/************************************************************************************************/
static void op_ldx_zpg()
{
am_zpg();
op_ldx();
}
/************************************************************************************************/
static void op_tay_imp()
{
op_tay();
}
/************************************************************************************************/
static void op_lda_imm()
{
am_imm();
op_lda();
}
/************************************************************************************************/
static void op_tax_imp()
{
op_tax();
}
/************************************************************************************************/
static void op_ldy_abs()
{
am_abs();
op_ldy();
}
/************************************************************************************************/
static void op_lda_abs()
{
am_abs();
op_lda();
}
/************************************************************************************************/
static void op_ldx_abs()
{
am_abs();
op_ldx();
}
/************************************************************************************************/
static void op_bcs_rel()
{
branch(d6502_f & FLAG_CARRY);
}
/************************************************************************************************/
static void op_lda_iny()
{
am_iny();
op_lda();
}
/************************************************************************************************/
static void op_ldy_zpx()
{
am_zpx();
op_ldy();
}
/************************************************************************************************/
static void op_lda_zpx()
{
am_zpx();
op_lda();
}
/************************************************************************************************/
static void op_ldx_zpy()
{
am_zpy();
op_ldx();
}
/************************************************************************************************/
static void op_clv_imp()
{
op_clv();
}
/************************************************************************************************/
static void op_lda_aby()
{
am_aby();
op_lda();
}
/************************************************************************************************/
static void op_tsx_imp()
{
op_tsx();
}
/************************************************************************************************/
static void op_ldy_abx()
{
am_abx();
op_ldy();
}
/************************************************************************************************/
static void op_lda_abx()
{
am_abx();
op_lda();
}
/************************************************************************************************/
static void op_ldx_aby()
{
am_aby();
op_ldx();
}
/************************************************************************************************/
static void op_cpy_imm()
{
am_imm();
op_cpy();
}
/************************************************************************************************/
static void op_cmp_inx()
{
am_inx();
op_cmp();
}
/************************************************************************************************/
static void op_cpy_zpg()
{
am_zpg();
op_cpy();
}
/************************************************************************************************/
static void op_cmp_zpg()
{
am_zpg();
op_cmp();
}
/************************************************************************************************/
static void op_dec_zpg()
{
am_zpg();
op_dec();
}
/************************************************************************************************/
static void op_iny_imp()
{
op_iny();
}
/************************************************************************************************/
static void op_cmp_imm()
{
am_imm();
op_cmp();
}
/************************************************************************************************/
static void op_dex_imp()
{
op_dex();
}
/************************************************************************************************/
static void op_cpy_abs()
{
am_abs();
op_cpy();
}
/************************************************************************************************/
static void op_cmp_abs()
{
am_abs();
op_cmp();
}
/************************************************************************************************/
static void op_dec_abs()
{
am_abs();
op_dec();
}
/************************************************************************************************/
static void op_bne_rel()
{
branch((d6502_f & FLAG_ZERO) == 0);
}
/************************************************************************************************/
static void op_cmp_iny()
{
am_iny();
op_cmp();
}
/************************************************************************************************/
static void op_cmp_zpx()
{
am_zpx();
op_cmp();
}
/************************************************************************************************/
static void op_dec_zpx()
{
am_zpx();
op_dec();
}
/************************************************************************************************/
static void op_cld_imp()
{
op_cld();
}
/************************************************************************************************/
static void op_cmp_aby()
{
am_aby();
op_cmp();
}
/************************************************************************************************/
static void op_cmp_abx()
{
am_abx();
op_cmp();
}
/************************************************************************************************/
static void op_dec_abx()
{
am_abx();
op_dec();
}
/************************************************************************************************/
static void op_cpx_imm()
{
am_imm();
op_cpx();
}
/************************************************************************************************/
static void op_sbc_inx()
{
am_inx();
op_sbc();
}
/************************************************************************************************/
static void op_cpx_zpg()
{
am_zpg();
op_cpx();
}
/************************************************************************************************/
static void op_sbc_zpg()
{
am_zpg();
op_sbc();
}
/************************************************************************************************/
static void op_inc_zpg()
{
am_zpg();
op_inc();
}
/************************************************************************************************/
static void op_inx_imp()
{
op_inx();
}
/************************************************************************************************/
static void op_sbc_imm()
{
am_imm();
op_sbc();
}
/************************************************************************************************/
static void op_nop_imp()
{
op_nop();
}
/************************************************************************************************/
static void op_cpx_abs()
{
am_abs();
op_cpx();
}
/************************************************************************************************/
static void op_sbc_abs()
{
am_abs();
op_sbc();
}
/************************************************************************************************/
static void op_inc_abs()
{
am_abs();
op_inc();
}
/************************************************************************************************/
static void op_beq_rel()
{
branch(d6502_f & FLAG_ZERO);
}
/************************************************************************************************/
static void op_sbc_iny()
{
am_iny();
op_sbc();
}
/************************************************************************************************/
static void op_sbc_zpx()
{
am_zpx();
op_sbc();
}
/************************************************************************************************/
static void op_inc_zpx()
{
am_zpx();
op_inc();
}
/************************************************************************************************/
static void op_sed_imp()
{
op_sed();
}
/************************************************************************************************/
static void op_sbc_aby()
{
am_aby();
op_sbc();
}
/************************************************************************************************/
static void op_sbc_abx()
{
am_abx();
op_sbc();
}
/************************************************************************************************/
static void op_inc_abx()
{
am_abx();
op_inc();
}
/************************************************************************************************/
static voidcall fulloptable[256] =
	{
	op_brk_imp,op_ora_inx,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_ora_zpg,op_asl_zpg,op_xxx_xxx, /* 00-07 */
	op_php_imp,op_ora_imm,op_asl_acc,op_xxx_xxx,op_xxx_xxx,op_ora_abs,op_asl_abs,op_xxx_xxx, /* 08-0f */
	op_bpl_rel,op_ora_iny,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_ora_zpx,op_asl_zpx,op_xxx_xxx, /* 10-17 */
	op_clc_imp,op_ora_aby,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_ora_abx,op_asl_abx,op_xxx_xxx, /* 18-1f */
	op_jsr_abs,op_and_inx,op_xxx_xxx,op_xxx_xxx,op_bit_zpg,op_and_zpg,op_rol_zpg,op_xxx_xxx, /* 20-27 */
	op_plp_imp,op_and_imm,op_rol_acc,op_xxx_xxx,op_bit_abs,op_and_abs,op_rol_abs,op_xxx_xxx, /* 28-2f */
	op_bmi_rel,op_and_iny,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_and_zpx,op_rol_zpx,op_xxx_xxx, /* 30-37 */
	op_sec_imp,op_and_aby,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_and_abx,op_rol_abx,op_xxx_xxx, /* 38-3f */
	op_rti_imp,op_eor_inx,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_eor_zpg,op_lsr_zpg,op_xxx_xxx, /* 40-47 */
	op_pha_imp,op_eor_imm,op_lsr_acc,op_xxx_xxx,op_jmp_abs,op_eor_abs,op_lsr_abs,op_xxx_xxx, /* 48-4f */
	op_bvc_rel,op_eor_iny,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_eor_zpx,op_lsr_zpx,op_xxx_xxx, /* 50-57 */
	op_cli_imp,op_eor_aby,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_eor_abx,op_lsr_abx,op_xxx_xxx, /* 58-5f */
	op_rts_imp,op_adc_inx,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_adc_zpg,op_ror_zpg,op_xxx_xxx, /* 60-67 */
	op_pla_imp,op_adc_imm,op_ror_acc,op_xxx_xxx,op_jmp_ind,op_adc_abs,op_ror_abs,op_xxx_xxx, /* 68-6f */
	op_bvs_rel,op_adc_iny,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_adc_zpx,op_ror_zpx,op_xxx_xxx, /* 70-77 */
	op_sei_imp,op_adc_aby,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_adc_abx,op_ror_abx,op_xxx_xxx, /* 78-7f */
	op_xxx_xxx,op_sta_inx,op_xxx_xxx,op_xxx_xxx,op_sty_zpg,op_sta_zpg,op_stx_zpg,op_xxx_xxx, /* 80-87 */
	op_dey_imp,op_xxx_xxx,op_txa_imp,op_xxx_xxx,op_sty_abs,op_sta_abs,op_stx_abs,op_xxx_xxx, /* 88-8f */
	op_bcc_rel,op_sta_iny,op_xxx_xxx,op_xxx_xxx,op_sty_zpx,op_sta_zpx,op_stx_zpy,op_xxx_xxx, /* 90-97 */
	op_tya_imp,op_sta_aby,op_txs_imp,op_xxx_xxx,op_xxx_xxx,op_sta_abx,op_xxx_xxx,op_xxx_xxx, /* 98-9f */
	op_ldy_imm,op_lda_inx,op_ldx_imm,op_xxx_xxx,op_ldy_zpg,op_lda_zpg,op_ldx_zpg,op_xxx_xxx, /* a0-a7 */
	op_tay_imp,op_lda_imm,op_tax_imp,op_xxx_xxx,op_ldy_abs,op_lda_abs,op_ldx_abs,op_xxx_xxx, /* a8-af */
	op_bcs_rel,op_lda_iny,op_xxx_xxx,op_xxx_xxx,op_ldy_zpx,op_lda_zpx,op_ldx_zpy,op_xxx_xxx, /* b0-b7 */
	op_clv_imp,op_lda_aby,op_tsx_imp,op_xxx_xxx,op_ldy_abx,op_lda_abx,op_ldx_aby,op_xxx_xxx, /* b8-bf */
	op_cpy_imm,op_cmp_inx,op_xxx_xxx,op_xxx_xxx,op_cpy_zpg,op_cmp_zpg,op_dec_zpg,op_xxx_xxx, /* c0-c7 */
	op_iny_imp,op_cmp_imm,op_dex_imp,op_xxx_xxx,op_cpy_abs,op_cmp_abs,op_dec_abs,op_xxx_xxx, /* c8-cf */
	op_bne_rel,op_cmp_iny,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_cmp_zpx,op_dec_zpx,op_xxx_xxx, /* d0-d7 */
	op_cld_imp,op_cmp_aby,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_cmp_abx,op_dec_abx,op_xxx_xxx, /* d8-df */
	op_cpx_imm,op_sbc_inx,op_xxx_xxx,op_xxx_xxx,op_cpx_zpg,op_sbc_zpg,op_inc_zpg,op_xxx_xxx, /* e0-e7 */
	op_inx_imp,op_sbc_imm,op_nop_imp,op_xxx_xxx,op_cpx_abs,op_sbc_abs,op_inc_abs,op_xxx_xxx, /* e8-ef */
	op_beq_rel,op_sbc_iny,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_sbc_zpx,op_inc_zpx,op_xxx_xxx, /* f0-f7 */
	op_sed_imp,op_sbc_aby,op_xxx_xxx,op_xxx_xxx,op_xxx_xxx,op_sbc_abx,op_inc_abx,op_xxx_xxx  /* f8-ff */
	};
/************************************************************************************************/
u16 dead6502_disassembleopcode(char *buffer,u16 opcodepos)
{
u8 opcode,size;
u16 addr;

strcpy(buffer,"");
opcode = d6502_op6502(opcodepos);
switch(addrtable[opcode])
	{
	case er:size = 1;SPRINTF(buffer,".u8 $%02x",opcode);break;
	case no:size = 1;SPRINTF(buffer,"%s\t",opcodes[opcode]);break;
	case ac:size = 1;SPRINTF(buffer,"%s\ta",opcodes[opcode]);break;
	case ab:
		size = 3;
		addr = d6502_read6502(opcodepos+1) | (d6502_read6502(opcodepos+2) << 8);
		if(addr < 0x100) //should be zero page, so its bad opcode
			{
			size = 1;
			SPRINTF(buffer,".u8 $%02x",opcode);
			break;
			}
		SPRINTF(buffer,"%s\t$%04x",opcodes[opcode],addr);
		break;
	case ax:
		size = 3;
		addr = d6502_read6502(opcodepos+1) | (d6502_read6502(opcodepos+2) << 8);
		if(addr < 0x100) //should be zero page, so its bad opcode
			{
			size = 1;
			SPRINTF(buffer,".u8 $%02x",opcode);
			break;
			}
		SPRINTF(buffer,"%s\t$%04x,x",opcodes[opcode],addr);
		break;
	case ay:
		size = 3;
		addr = d6502_read6502(opcodepos+1) | (d6502_read6502(opcodepos+2) << 8);
		if(addr < 0x100) //should be zero page, so its bad opcode
			{
			size = 1;
			SPRINTF(buffer,".u8 $%02x",opcode);
			break;
			}
		SPRINTF(buffer,"%s\t$%04x,y",opcodes[opcode],addr);
		break;
	case in:size = 3;SPRINTF(buffer,"%s\t($%04X)",opcodes[opcode],d6502_read6502(opcodepos+1) | (d6502_read6502(opcodepos+2) << 8));break;
	case im:size = 2;SPRINTF(buffer,"%s\t#$%02x",opcodes[opcode],d6502_read6502(opcodepos+1));break;
	case ix:size = 2;SPRINTF(buffer,"%s\t($%02x,x)",opcodes[opcode],d6502_read6502(opcodepos+1));break;
	case iy:size = 2;SPRINTF(buffer,"%s\t($%02x),y",opcodes[opcode],d6502_read6502(opcodepos+1));break;
	case re:size = 2;SPRINTF(buffer,"%s\tl%04x",opcodes[opcode],opcodepos+size+((s8)d6502_read6502(opcodepos+1)));break;
	case zp:size = 2;SPRINTF(buffer,"%s\t$%02x",opcodes[opcode],d6502_read6502(opcodepos+1));break;
	case zx:size = 2;SPRINTF(buffer,"%s\t$%02x,x",opcodes[opcode],d6502_read6502(opcodepos+1));break;
	case zy:size = 2;SPRINTF(buffer,"%s\t$%02x,y",opcodes[opcode],d6502_read6502(opcodepos+1));break;
	default:size = 1;SPRINTF(buffer,"disassembler bug");break;
	}
//_strupr(buffer); //upper case is easier to read
return(opcodepos + size);
}
/************************************************************************************************/
u8 dead6502_getlastopcode()
{
return(oldop);
}
/************************************************************************************************/
u16 dead6502_getlastopcodepc()
{
return(oldpc);
}
/************************************************************************************************/
u8 dead6502_getcurrentopcode()
{
return(saveop);
}
/************************************************************************************************/
u16 dead6502_getcurrentopcodepc()
{
return(savepc);
}
/************************************************************************************************/
u8 dead6502_getnextopcode()
{
return(d6502_op6502(savepc + oplength[saveop]));
}
/************************************************************************************************/
u16 dead6502_getnextopcodepc()
{
return(savepc + oplength[saveop]);
}
/************************************************************************************************/
u16 dead6502_getvector(u8 v)
{
switch(v)
	{
	case CPU_NMI:return(d6502_read6502(0xfffa) | (d6502_read6502(0xfffb) << 8));
	case CPU_RESET:return(d6502_read6502(0xfffc) | (d6502_read6502(0xfffd) << 8));
	case CPU_IRQ:return(d6502_read6502(0xfffe) | (d6502_read6502(0xffff) << 8));
	}
return(0);
}
/************************************************************************************************/
u32 dead6502_getcycles()
{
return(cyclesexec);
}
/************************************************************************************************/
void dead6502_addcycles(u32 numcycles)
{
cyclesexec += numcycles;
tcycles += numcycles;
}
/************************************************************************************************/
void dead6502_setdata(dead6502data *newdata)
{
data = newdata;
}
/************************************************************************************************/
void dead6502_getdata(dead6502data **newdata)
{
*newdata = data;
}
/************************************************************************************************/
void dead6502_init()
{
int i;

for(i=0;i<256;i++)
	{
	cycletable[i] = basecycletable[i];// * data->resoulution;
	nztable[i] = (i==0?2:i&0x80);
	switch(addrtable[i])
		{
		case er:
		case no:
		case ac:oplength[i] = 1;break;
		case im:
		case ix:
		case iy:
		case re:
		case zp:
		case zx:
		case zy:oplength[i] = 2;break;
		case ab:
		case ax:
		case ay:
		case in:oplength[i] = 3;break;
		}
	}
nmicycles = 7;
irqcycles = 7;
stop = 0;
}
/************************************************************************************************/
void dead6502_nmi()
{
d6502_needirq |= CPU_NMI;
}
/************************************************************************************************/
void dead6502_irq()
{
d6502_needirq |= CPU_IRQ;
}
/************************************************************************************************/
void dead6502_reset()
{
d6502_a = 0;
d6502_x = 0;
d6502_y = 0;
d6502_s = 0xff;
d6502_f = FLAG_XXX | FLAG_IRQDISABLE;
d6502_needirq = 0;
d6502_pc = dead6502_getvector(CPU_RESET);
d6502_totalcycles = 0;
addr = 0;
tcycles = 0;
}
/************************************************************************************************/
void dead6502_stop()
{
stop = 1;
}
/************************************************************************************************/
u32 dead6502_exec(u32 cycles)
{
#ifdef CPUDEBUG
char disasm[64];
#endif

cyclesexec = 0;
if(d6502_needirq)
	{
	if(d6502_needirq & CPU_NMI)
		{
		d6502_f &= ~(FLAG_BRK | FLAG_DECIMAL);
		push(d6502_pc >> 8);
		push(d6502_pc);
		push(d6502_f);
		d6502_pc = d6502_read6502(0xfffa);
		d6502_pc |= d6502_read6502(0xfffb) << 8;
		cyclesexec += nmicycles;;
		d6502_needirq &= NMI_MASK;
		}
	if(d6502_needirq & CPU_IRQ)
		{
		if((d6502_f & FLAG_IRQDISABLE) == 0)
			{
			d6502_f &= ~(FLAG_BRK | FLAG_DECIMAL);
			push(d6502_pc >> 8);
			push(d6502_pc);
			push(d6502_f);
			d6502_f |= FLAG_IRQDISABLE;
			d6502_pc = d6502_read6502(0xfffe);
			d6502_pc |= d6502_read6502(0xffff) << 8;
			cyclesexec += irqcycles;
			}
		d6502_needirq &= IRQ_MASK;
		}
	}
while(cyclesexec < cycles && stop == 0)
	{
	savepc = d6502_pc;
	saveop = d6502_opcode = d6502_op6502(d6502_pc++);
	if(fulloptable[d6502_opcode] != 0)
		{
		fulloptable[d6502_opcode]();
#ifdef CPUDEBUG
		dead6502_disassembleopcode(disasm,savepc);
		msg("$%04x: %02x:%s %02x %02x a:%02x x:%02x y:%02x s:%02x f:%02x\n",savepc,d6502_read6502(savepc),disasm,d6502_read6502(savepc+1),d6502_read6502(savepc+2),d6502_a,d6502_x,d6502_y,d6502_s,d6502_f);
#endif
		}
#ifndef SKIPBADOPS
	else
		{
		d6502_pc--; //return to the bad opcode
		d6502_totalcycles += cyclesexec; //add in cycles taken
		oldop = saveop;
		oldpc = savepc;
		return((u32)cyclesexec | BAD_OPCODE); /* bad opcode */
		}
#endif
	oldop = saveop;
	oldpc = savepc;
	cyclesexec += cycletable[d6502_opcode];
	}
stop = 0;
d6502_totalcycles += cyclesexec;
return(cyclesexec);
}
/************************************************************************************************/
u8 dead6502_read(u32 addr)
{
return(d6502_read6502(addr));
}
/************************************************************************************************/
void dead6502_write(u32 addr,u8 data)
{
d6502_write6502(addr,data);
}
/************************************************************************************************/
